#pragma once

#include "CDXBuffer.h"
#include "CDXTexture2D.h"
#include "CComm.h"

#ifndef __SWIG__
#include "d3dx11effect.h"
#include <map>
#include <string>
#else
#include "D3D11_swig.h"
#endif

class CDXEffect : public CDXBase, public CRefCount
{
protected:
#ifndef __SWIG__

	static std::map<std::wstring, ID3D10Blob*> ms_shaderCache;
	ID3DX11Effect* m_pEffect;
	ID3DBlob* m_pEffectBuffer;

	WCHAR m_path[MAX_PATH];

	UINT m_nResourceLockedCount;
	std::map<std::string, std::vector<CDXResource*>> m_pResourceByName;
	std::map<UINT, std::vector<CDXResource*>> m_pResourceByIndex;
	std::map<std::string, std::vector<CDXResource*>> m_pResourceBySemantic;

	


protected:
	virtual HRESULT _DispatchCS(ID3DX11EffectPass* pPass, UINT nThreadX, UINT nThreadY, UINT nThreadZ);
	HRESULT _CompileShaderFromFile(LPCWSTR szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut );
	HRESULT _LoadEffectFromFile(ID3D11Device* pDevice, LPCWSTR szFileName, ID3DBlob** ppEffectBuffer, ID3DX11Effect** ppEffect);

	virtual HRESULT _StoreResourceByName(CDXResource* pResource, std::string name);
	virtual HRESULT _StoreResourceByIndex(CDXResource* pResource, UINT index);
	virtual HRESULT _StoreResourceBySemantic(CDXResource* pResource, std::string semantic);
	virtual HRESULT _StoreResourceArrayByName(std::vector<CDXResource*> pResources, std::string name);
	virtual HRESULT _StoreResourceArrayByIndex(std::vector<CDXResource*> pResources, UINT index);
	virtual HRESULT _StoreResourceArrayBySemantic(std::vector<CDXResource*> pResources, std::string semantic);
	virtual HRESULT _ClearStoredResources();
#endif //#ifndef __SWIG__

public:
	CDXEffect(CDXDevice* pDevice);
	virtual ~CDXEffect();
	virtual HRESULT SetEffect(ID3DX11Effect* pEffect);
	virtual ID3DX11Effect* GetEffect();
	virtual ID3D10Blob* GetEffectBuffer();
	virtual HRESULT LoadFromFile(LPCWSTR szFileName);
	
	virtual HRESULT LockKeyMutexResources();
	virtual HRESULT UnLockKeyMutexResources();

	virtual HRESULT SetVariableByName(const char* varName, void* pValue, UINT offset, UINT nByte);
	virtual HRESULT SetVariableBySemantic(const char* sematic, void* pValue, UINT offset, UINT nByte);
	virtual HRESULT SetVariableByIndex(UINT idx, void* pValue, UINT offset, UINT nByte);

	
	virtual HRESULT SetMatrixVariableByName(const char* varName, float* pMatrix, bool bTranspose);
	virtual HRESULT SetMatrixVariableBySemantic(const char* sematic, float* pMatrix, bool bTranspose);
	virtual HRESULT SetMatrixVariableByIndex(UINT idx, float* pMatrix, bool bTranspose);
	
	virtual HRESULT SetMatrixArrayVariableByName(const char* varName, float* pMatrix, UINT offset, UINT nElem, bool bTranspose); //unit : element, not byte
	virtual HRESULT SetMatrixArrayVariableBySemantic(const char* sematic, float* pMatrix, UINT offset, UINT nElem, bool bTranspose); //unit : element, not byte
	virtual HRESULT SetMatrixArrayVariableByIndex(UINT idx, float* pMatrix, UINT offset, UINT nElem, bool bTranspose); //unit : element, not byte
	
	virtual HRESULT SetShaderResourceVariableByName(const char* varName, ID3D11ShaderResourceView* pSRV);
	virtual HRESULT SetShaderResourceVariableBySemantic(const char* sematic, ID3D11ShaderResourceView* pSRV);
	virtual HRESULT SetShaderResourceVariableByIndex(UINT idx, ID3D11ShaderResourceView* pSRV);
	virtual HRESULT SetShaderResourceVariableByName(const char* varName, CDXResource* pResource);
	virtual HRESULT SetShaderResourceVariableBySemantic(const char* sematic, CDXResource* pResource);
	virtual HRESULT SetShaderResourceVariableByIndex(UINT idx, CDXResource* pResource);

	virtual HRESULT SetShaderResourceArrayVariableByName(const char* varName, ID3D11ShaderResourceView** ppSRV, UINT offset, UINT nElem); //unit : element, not byte
	virtual HRESULT SetShaderResourceArrayVariableBySemantic(const char* sematic, ID3D11ShaderResourceView** ppSRV, UINT offset, UINT nElem); //unit : element, not byte
	virtual HRESULT SetShaderResourceArrayVariableByIndex(UINT idx, ID3D11ShaderResourceView** ppSRV, UINT offset, UINT nElem); //unit : element, not byte
	virtual HRESULT SetShaderResourceArrayVariableByName(const char* varName, CDXResource** ppResource, UINT offset, UINT nElem); //unit : element, not byte
	virtual HRESULT SetShaderResourceArrayVariableBySemantic(const char* sematic, CDXResource** ppResource, UINT offset, UINT nElem); //unit : element, not byte
	virtual HRESULT SetShaderResourceArrayVariableByIndex(UINT idx, CDXResource** ppResource, UINT offset, UINT nElem); //unit : element, not byte

	virtual HRESULT SetUnorderAccessViewVariableByName(const char* varName, ID3D11UnorderedAccessView* pUAV);
	virtual HRESULT SetUnorderAccessViewVariableBySemantic(const char* sematic, ID3D11UnorderedAccessView* pUAV);
	virtual HRESULT SetUnorderAccessViewVariableByIndex(UINT idx, ID3D11UnorderedAccessView* pUAV);
	virtual HRESULT SetUnorderAccessViewVariableByName(const char* varName, CDXResource* pResource);
	virtual HRESULT SetUnorderAccessViewVariableBySemantic(const char* sematic, CDXResource* pResource);
	virtual HRESULT SetUnorderAccessViewVariableByIndex(UINT idx, CDXResource* pResource);

	virtual HRESULT SetUnorderAccessVieweArrayVariableByName(const char* varName, ID3D11UnorderedAccessView** ppUAV, UINT offset, UINT nElem); //unit : element, not byte
	virtual HRESULT SetUnorderAccessViewArrayVariableBySemantic(const char* sematic, ID3D11UnorderedAccessView** ppUAV, UINT offset, UINT nElem); //unit : element, not byte
	virtual HRESULT SetUnorderAccessViewArrayVariableByIndex(UINT idx, ID3D11UnorderedAccessView** ppUAV, UINT offset, UINT nElem); //unit : element, not byte
	virtual HRESULT SetUnorderAccessVieweArrayVariableByName(const char* varName, CDXResource** ppResource, UINT offset, UINT nElem); //unit : element, not byte
	virtual HRESULT SetUnorderAccessViewArrayVariableBySemantic(const char* sematic, CDXResource** ppResource, UINT offset, UINT nElem); //unit : element, not byte
	virtual HRESULT SetUnorderAccessViewArrayVariableByIndex(UINT idx, CDXResource** ppResource, UINT offset, UINT nElem); //unit : element, not byte

	virtual HRESULT SetConstBufferVariableByName(const char* varName, ID3D11Buffer* pBuf);
	virtual HRESULT SetConstBufferVariableBySemantic(const char* sematic, ID3D11Buffer* pBuf);
	virtual HRESULT SetConstBufferVariableByIndex(UINT idx, ID3D11Buffer* pBuf);
	virtual HRESULT SetConstBufferVariableByName(const char* varName, CDXBuffer* pBuf);
	virtual HRESULT SetConstBufferVariableBySemantic(const char* sematic, CDXBuffer* pBuf);
	virtual HRESULT SetConstBufferVariableByIndex(UINT idx, CDXBuffer* pBuf);

	virtual HRESULT SetTextureBufferVariableByName(const char* varName, ID3D11ShaderResourceView* pSRV);
	virtual HRESULT SetTextureBufferVariableBySemantic(const char* sematic,ID3D11ShaderResourceView* pSRV);
	virtual HRESULT SetTextureBufferVariableByIndex(UINT idx, ID3D11ShaderResourceView* pSRV);
	virtual HRESULT SetTextureBufferVariableByName(const char* varName, CDXTexture2D* pTexture);
	virtual HRESULT SetTextureBufferVariableBySemantic(const char* sematic, CDXTexture2D* pTexture);
	virtual HRESULT SetTextureBufferVariableByIndex(UINT idx, CDXTexture2D* pTexture);

	virtual HRESULT DispatchCS(UINT idxTech, UINT idxPass, UINT nThreadX, UINT nThreadY, UINT nThreadZ);
	virtual HRESULT DispatchCSByName(const char* techName, const char* passName, UINT nThreadX, UINT nThreadY, UINT nThreadZ);

	static HRESULT CalcDispatchThread(UINT& nTX, UINT& nTY, UINT& nTZ, UINT nNeedEntry, UINT nThreadInFX);

};

